#include "Funcs.h"
#include "Spark/Utils/Logger.h"
#include <sstream>
#include <cxxabi.h>
#include <execinfo.h>

static std::string demangle(const char* str)
{
    size_t size{0};
    int status{0};
    char buf[256]{};
    if (sscanf(str, "%*[^(]%*[^_]%255[^)+]", buf) == 1)
    {
        char* s = abi::__cxa_demangle(buf, nullptr, &size, &status);
        if (s)
        {
            std::string ret(s, size);
            free(s);
            return ret;
        }
    }
    if (sscanf(str, "%255s", buf) == 1)
    {
        return buf;
    }
    return str;
}

void backTrace(std::vector<std::string>& bt, int size, int skip)
{
    void** array = static_cast<void**>(malloc(sizeof(void*) * size));
    size_t stacks = ::backtrace(array, size);
    char** strings = ::backtrace_symbols(array, stacks);
    if (strings == nullptr)
    {
        LOG_FATAL << "in backTrace(), ::backtrace_symbols() error";
        free(array);
        return;
    }
    for (size_t i = skip; i < stacks; ++i)
    {
        bt.emplace_back(demangle(strings[i]));
    }
    free(strings);
    free(array);
}

std::string backTraceToString(int size, int skip, const std::string& prefix)
{
    std::vector<std::string> bt;
    backTrace(bt, size, skip);
    std::stringstream ss;
    for (size_t i = 0; i < bt.size(); ++i)
    {
        ss << prefix << bt[i] << std::endl;
    }
    return ss.str();
}